package SO.Operaciones;

import SBD.CRUD.OperacionesBD;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

/**
* @class Operaciones
* @author Mauricio Alvarez.
* @brief Esta clase contiene métodos de utilidad para parseo, extracción de terminos, consultas, Stopwords, etc.
*/
public class Operaciones {

    /**
     *  @var private OperacionesBD opbd
     *  @brief Variable global de tipo clase OperacionesBD.
    */
    private OperacionesBD opbd;


    //////////////////////////
    // CONSTRUCTOR
    //////////////////////////

    public Operaciones()
    {
        opbd = new OperacionesBD();
    }


    //////////////////////////
    // CONSULTA (TERMINOS)
    //////////////////////////

    /**
     * @brief Transforma los terminos de la consulta a minusculas y sin acentos.
     * @param Terminos de la consulta
     * @return void
    */
    public String FormatearConsulta (String Consulta)
    {
        return Consulta.toLowerCase().replaceAll("á", "a").
                                      replaceAll("é", "e").
                                      replaceAll("í", "i").
                                      replaceAll("ó", "o").
                                      replaceAll("ú", "u").
                                      replaceAll("à", "a").
                                      replaceAll("è", "e").
                                      replaceAll("ì", "i").
                                      replaceAll("ò", "o").
                                      replaceAll("ù", "u").
                                      replaceAll("ä", "a").
                                      replaceAll("ë", "e").
                                      replaceAll("ï", "i").
                                      replaceAll("ö", "o").
                                      replaceAll("ü", "u");
    }//FIN FormatearConsulta (OK)


    /**
     * @brief Tokeniza los terminos de la consulta guardándolo en una HashMap.
     * @param Terminos de la consulta
     * @return Map<String, Integer>
    */
    public Map<String, Integer> ObtenerPalabrasConsulta (String consulta, Map<String, Integer> Stopwords)
    {
        Map<String, Integer> ListaTerminos = new HashMap();
        int index = 0;
        Pattern p = Pattern.compile("[a-zA-Z0-9áéíóúÁÉÍÓÚ]+");
        Matcher m = p.matcher(FormatearConsulta(consulta));
        while (m.find())
        {
            String palabra = m.group();
            ///////////////////////////////////////////////
            //PASO 2: Extrae del documento los STOPWORD
            ///////////////////////////////////////////////
            if (Stopwords.containsKey(palabra)==false)
            { 
                ///////////////////////////////////////////////////////////////////
                //PASO 3: Se obtiene la frecuencia de veces que aparece ese termino
                ///////////////////////////////////////////////////////////////////
                if (ListaTerminos.containsKey(palabra)==false)
                {
                    //Se ingresa por primera vez:
                    ListaTerminos.put(m.group(), 1);
                }else{
                    //Se aumenta la frecuencia:
                    int frecuencua = ((Integer)ListaTerminos.get("Rohit")).intValue();
                    ListaTerminos.put(palabra, new Integer(frecuencua + 1000));
                }
            }

        }

        return ListaTerminos;

    }//FIN ObtenerPalabrasConsulta (OK)


    /**
     * @brief Extrae los stopwords de los terminos de la ontología.
     * @param Listado de terminos del tópico y listado de stopwords
     * @return Map<String, Integer>
    */
    public Map<String, Integer> ObtenerPalabrasTopico(Map<String, Integer> Topico, Map<String, Integer> Stopwords)
    {

        Map<String,Integer> BOWTopico = new HashMap();
        Set set = Topico.entrySet();
        Iterator i = set.iterator();

        while(i.hasNext())
        {
            Map.Entry me = (Map.Entry)i.next();
            String termino = FormatearConsulta((String) me.getKey());

            Pattern p = Pattern.compile("[a-zA-Z0-9áéíóúÁÉÍÓÚ]+");
            Matcher m = p.matcher(termino);

            while (m.find())
            {
                String palabra = m.group();

                ///////////////////////////////////////////////
                //PASO 2: Extrae del documento los STOPWORD
                ///////////////////////////////////////////////
                if (Stopwords.containsKey(palabra)==false){
                    BOWTopico.put(palabra, 0);
                }
            }

        }

        return BOWTopico;

    }//FIN ObtenerPalabrasTopico (OK)

    
    //////////////////////////
    // STOPWORDS
    //////////////////////////

    /**
     * @brief Lee el archivo de texto con los stopword para que sean guardados }
     * posteriormente en la BD.
     * @param no tiene.
     * @return void
    */
    public void GuardarStopwords() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException
    {
        //////////////////////////////////////////////////
        //PASO 1: Lectura del archivo de texto (ESPAÑOL)
        //////////////////////////////////////////////////
        try {
            FileInputStream fis = new FileInputStream("C:\\Documents and Settings\\Mauricio\\Mis documentos\\NetBeansProjects\\Filtro\\Stopwords\\stopwords_es.txt");
            InputStreamReader is = new InputStreamReader(fis, "ISO-8859-1");
            BufferedReader bf = new BufferedReader(is);
            String linea;
            ArrayList Stopwords = new ArrayList();

            while ((linea = bf.readLine()) != null) {
                  Stopwords.add(linea);
            }
            fis.close();

            /////////////////////////////////////////////
            //PASO 2: Se guarda en la BD
            /////////////////////////////////////////////
            OperacionesBD operacionesbd = new OperacionesBD();
            operacionesbd.GuardarStopwords(Stopwords);

            } catch (FileNotFoundException e) {
                System.out.println("Archivo no encontrado");
            } catch (IOException e) {
                System.out.println("Error de E/S");
            }
        
    }//FIN GuardarStopwords (OK)
    
  
    /**
     * @brief Carga los STOPWORD de la BD en un MAP.
     * @param no tiene.
     * @return Map<String,Integer>
    */
    public Map<String,Integer> CargarStopwords() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, SQLException
    {
        return opbd.CargarStopwords();

    }//FIN CargarStopwords (OK)



    /**
     * @brief Borra los STOPWORD de la BD.
     * @param no tiene.
     * @return void
    */
    public void BorrarStopwords() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, SQLException
    {
        opbd.BorrarStopwords();
        
    }//FIN BorrarStopwords (OK)


    //////////////////////////
    // PÁGINAS
    //////////////////////////

    /**
     * @brief Extrae los terminos del contenido de las páginas si los stopwords.
     * @param El contenido de la página y el listado de stopwords.
     * @return List<String>
    */
    public List<String> ObtenerPalabrasPagina(String Pagina, Map<String, Integer> Stopwords) throws FileNotFoundException, IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException{

        /////////////////////////////////////////////////////////////////////////////////////
        //PASO 1: Limpiar la pagina de los TAG HTML extrayendo solo las palabras del BODY:
        /////////////////////////////////////////////////////////////////////////////////////
        List<String> PalabrasPagina = new ArrayList();

        Document doc = Jsoup.parse(Pagina);
        String contenido= doc.body().text();

        //El patrón NO considera los siguientes formatos:
        // + Fechas: las toma como 3 numeros (Ej: 12-12-2010)
        Pattern p = Pattern.compile("[a-zA-Z0-9áéíóúÁÉÍÓÚàèìòùäëïöü]+");
        Matcher m = p.matcher(contenido);

        while (m.find())
        {
            String termino = m.group().toLowerCase();
            
            ///////////////////////////////////////////////
            //PASO 2: Extrae del documento los STOPWORD
            ///////////////////////////////////////////////
            if (Stopwords.containsKey(termino)==false)
            {
                PalabrasPagina.add(FormatearConsulta(termino));
            }
        }

        return PalabrasPagina;

    }//FIN ObtenerPalabras (OK)


    //////////////////////////
    // DICCIONARIO
    //////////////////////////

    /**
     * @brief Genera el diccionario o vocabulario uniendo los terminos del tópico y la página.
     * @param El listado de terminos del tópico y de la página.
     * @return Set<String>
    */
    public Set<String> GenerarDiccionario(Map BoWtopico, Map<String, Integer> ContenidoPagina)
    {

        ////////////////////////////////////////////////////////////////////////
        //PASO 1: Se genera un set con la union de las palabras de al ontologia
        //        y la página.
        ////////////////////////////////////////////////////////////////////////

        Set Diccionario = new HashSet();

        //Palabras de la página:
        Set set = ContenidoPagina.entrySet();
        Iterator i = set.iterator();

        while(i.hasNext())
        {
          Map.Entry me = (Map.Entry)i.next();
          Diccionario.add(me.getKey());
        }

        //Palabras de la Ontología:
        set = BoWtopico.entrySet();

        while(i.hasNext())
        {
          Map.Entry me = (Map.Entry)i.next();
          Diccionario.add(me.getKey());
        }

        //////////////////////////////////
        //PASO 2: Retornar Diccionario
        //////////////////////////////////
        return (HashSet) Diccionario;

    }//FIN GenerarDicccionario (OK)



    //////////////////////////
    // VECTORES
    //////////////////////////

    /**
     * @brief Genera el vector binario del tópico con respecto al diccionario.
     * @param El conjunto de terminos del diccionario y el listado de terminos del topico.
     * @return double[][]
    */
    public double[][] GenerarVectorTopico(Set<String> Diccionario, Map Topico)
    {
        //////////////////////////////////
        //PASO 1: Recorrer Diccionario
        //////////////////////////////////
        double[][] Vector = new double[1][Diccionario.size()];
        int j = 0;

        Iterator iter = Diccionario.iterator();
        while (iter.hasNext())
        {
            String termino = FormatearConsulta(iter.next().toString());
            if (Topico.containsKey(termino) == true)
            {
                Vector[0][j] = 1;
                //System.out.println("Ter. Diccionario: "+ termino +" - Vtopico["+0+"]["+j+"] = "+Vector[0][j]);
            }else{
                Vector[0][j] = 0;
                //System.out.println("Ter. Diccionario: "+ termino +" - Vtopico["+0+"]["+j+"] = "+Vector[0][j]);
            }
            j++;
        }

        return Vector;

    }//FIN GenerarVectorBinarioTopico (OK)



    /**
     * @brief Genera el vector binario de la página con respecto al diccionario.
     * @param El conjunto de terminos de la página (contenido) y los terminos del diccionario.
     * @return double[][]
    */
    public double[][] GenerarVectorContenido(Set<String> Diccionario, Map Contenido)
    {
        //////////////////////////////////
        //PASO 1: Recorrer Diccionario
            //////////////////////////////////
        double[][] Vector = new double[1][Diccionario.size()];
        int j = 0;

        Iterator iter = Diccionario.iterator();
        while (iter.hasNext())
        {
            String termino = iter.next().toString();
            if (Contenido.containsKey(termino) == true)
            {
                Vector[0][j] = Double.valueOf(Contenido.get(termino).toString());
                //System.out.println("Ter. Diccionario: "+ termino +" - Vpagina["+0+"]["+j+"] = "+Vector[0][j]);
            }else{
                Vector[0][j] = 0;
                //System.out.println("Ter. Diccionario: "+ termino +" - Vpagina["+0+"]["+j+"] = "+Vector[0][j]);
            }
            j++;
        }

        return Vector;

    }//FIN GenerarVectorBinario (OK)


    //////////////////////////
    // MEDICIONES
    //////////////////////////

    /**
     * @brief Borra todas las mediciones obtenidas por el análisis de las metricas.
     * @param no tiene.
     * @return void
    */
    public void BorrarMediciones() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, SQLException
    {
        opbd.BorrarMediciones();

    }//FIN BorrarMediciones (OK)

    public void BorrarPaginas() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, SQLException 
    {
        opbd.BorrarPaginas();
    }



}//FIN CLASE Operaciones
